package com.orangelife.service.bill.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.orangelife.common.MybaitsGenericDaoSubLogic;
import com.orangelife.exception.AppBizException;
import com.orangelife.service.PropFeeType.IPropFeeTypeService;
import com.orangelife.service.base.modle.ResultInfo;
import com.orangelife.service.bill.IBillService;
import com.orangelife.service.bill.IComputeBillService;
import com.orangelife.service.bill.model.PreDetail;
import com.orangelife.service.feeDetail.IFeeDetailService;
import com.orangelife.service.offset.IOffsetService;
import com.orangelife.service.propFeeAccount.IPropFeeAccountService;
import com.orangelife.service.propFeeComm.IPropFeeCommService;
import com.orangelife.service.propFeeCommInfo.IPropFeeCommInfoService;
import com.orangelife.service.propFeeCommInfo.model.PropFeeCommInfoDto;
import com.orangelife.service.propFeeComputeRule.IPropFeeComputeRuleService;
import com.orangelife.service.propFeeComputeRule.model.Rule;
import com.orangelife.service.propFeeMeter.IPropFeeMeterService;
import com.orangelife.service.propinfo.IPropInfoService;
import com.orangelife.service.propinfo.model.QueryModel;
import com.orangelife.utils.DateUtil;
import com.orangelife.utils.IdUtil;
import com.orangelife.utils.PropertyUtils;
import com.orangelife.utils.StringUtils;
import com.orangelife.webservice.service.bill.entity.BillDto;
import com.orangelife.webservice.service.bill.entity.PreFeeDto;

@Service("computeBillService")
public class ComputeServiceImpl extends MybaitsGenericDaoSubLogic implements
		IComputeBillService {
	@Resource(name = "propFeeComputeRuleService")
	private IPropFeeComputeRuleService propFeeComputeRuleService;
	@Resource(name = "propFeeCommInfoService")
	private IPropFeeCommInfoService propFeeCommInfoService;
	@Resource(name = "propFeeCommService")
	private IPropFeeCommService propFeeCommService;

	@Resource(name = "propInfoService")
	private IPropInfoService propInfoService;
	@Resource(name = "propFeeMeterService")
	private IPropFeeMeterService propFeeMeterService;
	@Resource(name = "propFeeTypeService")
	private IPropFeeTypeService propFeeTypeService;
	@Resource(name = "propFeeAccountService")
	private IPropFeeAccountService propFeeAccountService;
	@Resource(name = "feeDetailService")
	private IFeeDetailService feeDetailService;
	@Resource(name = "offsetService")
	private IOffsetService offsetService;
	@Resource(name = "billService")
	private IBillService billService;

	@Override
	@Transactional(rollbackFor = { AppBizException.class, Exception.class,
			RuntimeException.class })
	public void startCreFeeDetail(BillDto billDto) throws AppBizException,
			Exception {

		// 要生成的房屋信息 1根据房屋id,2根据单元，3根据楼栋，4根据小区
		String type = "4";
		if (billDto.getApartmentIDs() != null
				&& billDto.getApartmentIDs().length > 0) {
			type = "1";

		} else if (!StringUtils.isBlank(billDto.getUnitID())) {

			type = "2";
		} else if (!StringUtils.isBlank(billDto.getBuildingID())) {

			type = "3";
		}
		List<Map<String, Object>> apartList = null;
		if ("1".equals(type)) {

			// apartList=this.getApartmentInfo(billDto.getApartmentIDs());

		}
		if ("4".equals(type)) {
			// apartList=this.getApartmentInfoListByCommID(commID);

		}

		// 获取有效的规则
		List<Rule> rules = this.getAllRuleByCommID(billDto.getCommID(),
				billDto.getStartTime(), billDto.getEndTime(),
				billDto.getIsPre());
		// 验证规则是否有效，和计算参数是否齐全

		String errInfo = "";
		boolean isErr = false;
		for (Rule rule2 : rules) {
			rule2.setStartDate(billDto.getStartTime());
			rule2.setEndDate(billDto.getEndTime());
			if (!propFeeComputeRuleService
					.checkRule(billDto.getCommID(), rule2).getCheckRes()) {
				isErr = true;
				errInfo = rule2.getErrInfo();
				break;
				// continue;
			}

			// System.out.println(rule2.complete(param));
		}
		if (isErr) {

			throw new AppBizException(100001, errInfo);
		}

		Map<String, String> commparam = new HashMap<>();
		BigDecimal res = null;

		for (Rule rule2 : rules) {
			// 获取关联的用户信息
			List<Map<String, Object>> apartments = propFeeComputeRuleService
					.getApartmentsByRuleID(rule2.getRuleID());

			// 每个关联房屋进行计算
			for (Map<String, Object> map : apartments) {
				// 设置计算参数
				propFeeComputeRuleService.setRuleParam(rule2, map, commparam);
				// 计算结果
				res = rule2.complete(rule2.getParam());
				// 插入缴费细项
				if (res != null
						&& BigDecimal.ZERO.compareTo(res.setScale(
								rule2.getRound(), BigDecimal.ROUND_HALF_UP)) < 0) {
					// 根据规则获取要生成的日期遍历生成账单
					for (String date : rule2.getResList(res.toString())) {
						Map<String, Object> p = new HashMap<String, Object>();
						p.put("feeDetailID", IdUtil.getuuId());
						p.put("apartmentID", map.get("apartmentID"));
						p.put("feeTypeID", rule2.getFeeTypeID());
						p.put("amount",
								res.setScale(rule2.getRound(),
										BigDecimal.ROUND_HALF_UP).toString());
						p.put("realamount",
								res.setScale(rule2.getRound(),
										BigDecimal.ROUND_HALF_UP).toString());
						// p.put("feeAmount", billParms.getAmount());
						// p.put("feePrice", billParms.getPrice());
						p.put("ruleID", rule2.getRuleID());
						p.put("feeDate", date);
						p.put("status", "0");
						p.put("itemStat", "1");
						p.put("planID", billDto.getPlanID());
						int r = this.addFeeDetail(p);
						// 设置原先预缴项为生成状态
						if (r == 0) {
							feeDetailService.updateType(map.get("apartmentID")
									.toString(), rule2.getFeeTypeID(), billDto
									.getStartTime(), "1", billDto.getPlanID());
						}

					}

				}

			}

		}

		Map<String, Object> param = new HashMap<String, Object>();
		param.put("commID", billDto.getCommID());
		param.put("code", "curDate");
		List<Map<String, Object>> p = propFeeCommInfoService
				.bauthfindPropFeeCommInfoByMap(param);

		if (p == null || p.size() == 0 || p.size() > 1) {

			throw new AppBizException(100001, "参数未配置");

		}

		Map<String, Object> res1 = p.get(0);
		PropFeeCommInfoDto pp = new PropFeeCommInfoDto();
		pp.setCommID(billDto.getCommID());
		pp.setInfoID(res1.get("info_id").toString());
		pp.setVal(billDto.getEndTime());
		propFeeCommInfoService.editPropFeeCommInfo(pp);

		/* 把表读数下移一期 */
		billService.updateMerRecordStatus(billDto.getCommID(), "2", "3", null);
		billService.updateMerRecordStatus(billDto.getCommID(), "1", "2", null);
		billService.updateMerRecordStatus(billDto.getCommID(), "0", "1", null);

	}

	/**
	 * 
	 * 添加缴费细项
	 * */
	public int addFeeDetail(Map<String, Object> param) {

		return this.getSqlSession().insert(
				"CollectionItemMapper.insertfeedetail2", param);

	}

	private List<Rule> getAllRuleByCommID(String commID, String startDate,
			String endDate, String isPre) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("commID", commID);
		param.put("startDate", startDate);
		param.put("endDate", endDate);
		param.put("isPre", isPre);
		List<Rule> ruleList = this.getSqlSession().selectList(
				"computeRuleMapper.findAllPropFeeComputeRule", param);

		return ruleList;
	}

	private List<Rule> getPreRule(String commID, String apartmentID,
			String feeTypeID, String date) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("commID", commID);
		param.put("apartmentID", apartmentID);
		param.put("feeTypeID", feeTypeID);
		param.put("date", date);
		List<Rule> ruleList = this.getSqlSession().selectList(
				"computeRuleMapper.selectRulesByPreType", param);

		return ruleList;
	}

	private List<Rule> getRuleByFeeTypeID(String commID, String apartmentID,
			String date) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("commID", commID);
		param.put("apartmentID", apartmentID);
		param.put("date", date);
		List<Rule> ruleList = this.getSqlSession().selectList(
				"computeRuleMapper.selectRulesByPreType", param);

		return ruleList;
	}

	@Override
	public List<Map<String, Object>> preFeeDetail(BillDto billDto)
			throws AppBizException {

		String commID = billDto.getCommID();
		String apartmentID = billDto.getApartmentID();
		String[] feeTypeIDs = billDto.getFeeTypeIDs();
		String startTime = billDto.getStartTime();
		String endTime = billDto.getEndTime();

		List<Map<String, Object>> res = new ArrayList<>();

		// 获取该房屋可以预缴的缴费类目(单房屋)

		List<Rule> rules = this.getPreRule(commID, apartmentID, null,
				billDto.getStartTime());

		if (rules == null || rules.size() == 0) {

			return null;
		}
		// 获取房屋信息

		Map<String, Object> apart = propInfoService
				.getApartmentInfo(apartmentID);
		// 计算预缴金额
		if (apart == null) {

			return null;
		}
		apart = PropertyUtils.turnToEntity1(apart);
		List<String> feeTypeIDs2 = new ArrayList<>();
		for (Rule rule : rules) {

			rule.init(false);
			if (rule.getIsValid() == -1) {
				continue;
			}
			propFeeComputeRuleService.checkRule(commID, rule);

			if (!rule.getCheckRes()) {

				continue;

			}
			propFeeComputeRuleService.setRuleParam(rule, apart, null);

			BigDecimal d = rule.complete(rule.getParam());
			if (d != null) {

				d = d.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP);

				if (d.compareTo(BigDecimal.ZERO) > 0) {

					Map<String, Object> param = new HashMap<>();
					param.put("amount", d);
					param.put("feeTypeID", rule.getFeeTypeID());
					param.put("isEvery", rule.getIsEvery());
					param.put("periodType", rule.getPeriodType());
					param.put("feeTypeName", rule.getFeeTypeName());
					feeTypeIDs2.add(rule.getFeeTypeID());
					res.add(param);
				}

			}

		}

		if (feeTypeIDs2 == null || feeTypeIDs2.size() == 0) {

			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("apartmentID", apartmentID);
		map.put("FeeTypeIDs", feeTypeIDs2);
		// 获取预缴项目的最新缴费日期
		Map<String, Map<String, Object>> list1 = this.getSqlSession()
				.selectMap("PropFeeDetailMapper.getMinDate", map, "feeTypeID");

		String curDate = null;

		curDate = propFeeCommInfoService.findValByCode(commID, "curDate");
		String date = null;

		for (Map<String, Object> map2 : res) {
			Map rr = list1.get(StringUtils.toString(map2.get("feeTypeID")));

			date = null;
			if (rr == null || rr.get("maxdate") == null) {
				date = curDate;
			} else {

				if (StringUtils.toString(rr.get("maxdate")).compareTo(curDate) < 0) {

					date = curDate;

				} else {
					date = StringUtils.toString(rr.get("maxdate"));
				}

			}

			map2.put("date", date);

		}

		return res;
	}

	@Override
	@Transactional(rollbackFor = { AppBizException.class, Exception.class,
			RuntimeException.class })
	public void startCreFeeDetail(BillDto billDto, List<Rule> rules)
			throws Exception, AppBizException {

		Map<String, String> commparam = new HashMap<>();
		BigDecimal res = null;

		for (Rule rule2 : rules) {
			// 获取关联的用户信息
			List<Map<String, Object>> apartments = propFeeComputeRuleService
					.getApartmentsByRuleID(rule2.getRuleID());

			// 每个关联房屋进行计算
			for (Map<String, Object> map : apartments) {
				// 设置计算参数
				propFeeComputeRuleService.setRuleParam(rule2, map, commparam);
				// 计算结果
				res = rule2.complete(rule2.getParam());

				// 插入缴费细项
				if (res != null
						&& BigDecimal.ZERO.compareTo(res.setScale(
								rule2.getRound(), BigDecimal.ROUND_HALF_UP)) < 0) {
					// 根据规则获取要生成的日期遍历生成账单
					for (String date : rule2.getResList(res.toString())) {
						Map<String, Object> p = new HashMap<String, Object>();
						p.put("feeDetailID", IdUtil.getuuId());
						p.put("apartmentID", map.get("apartmentID"));
						p.put("feeTypeID", rule2.getFeeTypeID());
						p.put("amount",
								res.setScale(rule2.getRound(),
										BigDecimal.ROUND_HALF_UP).toString());
						p.put("realamount",
								res.setScale(rule2.getRound(),
										BigDecimal.ROUND_HALF_UP).toString());

						p.put("feeAmount", rule2.getFeeAmount());
						p.put("feePrice", rule2.getFeePrice());

						p.put("ruleID", rule2.getRuleID());
						p.put("feeDate", date);
						p.put("status", "0");
						p.put("itemStat", "1");
						p.put("planID", billDto.getPlanID());
						int r = this.addFeeDetail(p);
						// 设置原先预缴项为生成状态
						if (r == 0) {
							feeDetailService.updateType(map.get("apartmentID")
									.toString(), rule2.getFeeTypeID(), date,
									"1", billDto.getPlanID());
						}

					}

				}

			}

		}

		Map<String, Object> param = new HashMap<String, Object>();
		param.put("commID", billDto.getCommID());
		param.put("code", "curDate");
		List<Map<String, Object>> p = propFeeCommInfoService
				.bauthfindPropFeeCommInfoByMap(param);

		if (p == null || p.size() == 0 || p.size() > 1) {

			throw new AppBizException(100001, "参数未配置");

		}

		Map<String, Object> res1 = p.get(0);
		PropFeeCommInfoDto pp = new PropFeeCommInfoDto();
		pp.setCommID(billDto.getCommID());
		pp.setInfoID(res1.get("info_id").toString());
		pp.setVal(billDto.getEndTime());

		// 更新当期期数
		propFeeCommInfoService.editPropFeeCommInfo(pp);

		// 表读数进行处理
		propFeeMeterService.dealMeterRecord(billDto.getCommID(),
				billDto.getEndTime());

	}

	@Override
	public Map<String, Object> checkRules(BillDto billDto) throws Exception,
			AppBizException {

		Map<String, Object> res = new HashMap<String, Object>();
		res.put("errCode", 0);
		// 要生成的房屋信息 1根据房屋id,2根据单元，3根据楼栋，4根据小区
		String type = "4";
		if (billDto.getApartmentIDs() != null
				&& billDto.getApartmentIDs().length > 0) {
			type = "1";

		} else if (!StringUtils.isBlank(billDto.getUnitID())) {

			type = "2";
		} else if (!StringUtils.isBlank(billDto.getBuildingID())) {

			type = "3";
		}
		if ("1".equals(type)) {

			// apartList=this.getApartmentInfo(billDto.getApartmentIDs());

		}
		if ("4".equals(type)) {
			// apartList=this.getApartmentInfoListByCommID(commID);

		}

		// 获取有效的规则
		List<Rule> rules = this.getAllRuleByCommID(billDto.getCommID(),
				billDto.getStartTime(), billDto.getEndTime(),
				billDto.getIsPre());
		// 验证规则是否有效，和计算参数是否齐全

		String errInfo = "";
		boolean isErr = false;
		for (Rule rule2 : rules) {
			rule2.setStartDate(billDto.getStartTime());
			rule2.setEndDate(billDto.getEndTime());
			if (!propFeeComputeRuleService
					.checkRule(billDto.getCommID(), rule2).getCheckRes()) {
				isErr = true;
				errInfo = rule2.getErrInfo();
				break;
				// continue;
			}

			// System.out.println(rule2.complete(param));
		}
		if (isErr) {

			res.put("errCode", "100001");
			res.put("errInfo", StringUtils.toString(errInfo, ""));

			return res;
			// throw new AppBizException(100001, errInfo);
		}

		res.put("rules", rules);

		return res;

	}

	// @Override
	// public List<Map<String, Object>> crePreFeeDetail(BillDto billDto)
	// throws AppBizException {
	// // TODO Auto-generated method stub
	// return null;
	// }
	@Override
	public List<Map<String, Object>> getPreFeeDetail(String commID,
			String apartmentID, List<PreFeeDto> preFeeDto)
			throws AppBizException, Exception {

		List<Map<String, Object>> res = new ArrayList<>();
		for (PreFeeDto preFeeDto2 : preFeeDto) {
			// 根据房屋id,和类型获取规则
			List<Rule> rules = this.getPreRule(commID, apartmentID,
					preFeeDto2.getFeeTypeID(), null);
			if (rules == null || rules.size() == 0 || rules.size() > 1) {

				throw new AppBizException(100001, "预缴规则异常");

			}

			Rule rule = rules.get(0);
			rule.init(false);
			if (rule.getIsValid() == -1) {
				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常");
			}
			rule.setStartDate(preFeeDto2.getStartTime());
			rule.setEndDate(preFeeDto2.getEndTime());
			Map<String, Object> apart = propInfoService
					.getApartmentInfo(apartmentID);
			// 计算预缴金额
			if (apart == null) {

				return null;
			}

			apart = PropertyUtils.turnToEntity1(apart);
			propFeeComputeRuleService.checkRule(commID, rule);
			if (!rule.getCheckRes()) {

				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常请检查");

			}
			propFeeComputeRuleService.setRuleParam(rule, apart, null);

			BigDecimal d = rule.complete(rule.getParam());

			if (d != null) {

				d = d.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP);

				if (d.compareTo(BigDecimal.ZERO) > 0) {

					for (String date : rule.getResList2(d.toString())) {
						Map<String, Object> param = new HashMap<>();
						param.put("amount", d.toString());
						param.put("feeTypeID", rule.getFeeTypeID());
						param.put("feeDate", date);
						param.put("ruleID", rule.getRuleID());

						param.put("feeAmount", rule.getFeeAmount());
						param.put("feePrice", rule.getFeePrice());

						param.put("feeTypeName", rule.getFeeTypeName());

						res.add(param);

					}

				}
			} else {

				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常");

			}

		}
		return res;
	}

	@Override
	public Map<String, Map<String, PreDetail>> commPreFeeDetail(
			BillDto billDto, List<Map<String, Object>> aparts)
			throws AppBizException, Exception {
		// 需要查询的房屋信息
		List<Map<String, Object>> apartList = null;
		if (aparts == null) {

			// 要生成的房屋信息 1根据房屋id,2根据单元，3根据楼栋，4根据小区
			String type = "4";
			QueryModel q = new QueryModel();
			if (billDto.getApartmentIDs() != null
					&& billDto.getApartmentIDs().length > 0) {
				type = "1";

				q.setApartmentIDs(billDto.getApartmentIDs());

			} else if (billDto.getUnitIDs() != null
					&& billDto.getUnitIDs().length > 0) {
				q.setUnitIDs(billDto.getUnitIDs());
				type = "2";
			} else if (billDto.getBuildingIDs() != null
					&& billDto.getBuildingIDs().length > 0) {
				q.setBuildingIDs(billDto.getBuildingIDs());
				type = "3";
			} else {

				q.setCommID(billDto.getCommID());

			}
			apartList = propInfoService.getApartmentInfo(q);
		} else {

			apartList = aparts;

		}

		String commID = billDto.getCommID();
		String startTime = billDto.getStartTime();
		String endTime = billDto.getEndTime();
		String tempDate = null;
		String code = null;
		Map<String, Map<String, PreDetail>> res = new HashMap<String, Map<String, PreDetail>>();
		Map<String, Rule> ruleList = new HashMap<String, Rule>();
		// Map<String,Map<String>>

		List<Map<String, Object>> types = propFeeTypeService
				.getPropFeeTypeLevel(commID, null);
		// feeTypeID与code对应
		Map<String, String> codes = new HashMap<String, String>();
		for (Map<String, Object> map : types) {
			codes.put(map.get("feeTypeID").toString(), map.get("code")
					.toString());
		}
		// List<String> feeTypeIDs=

		BigDecimal temp = BigDecimal.ZERO;
		for (Map<String, Object> apartmentInfo : apartList) {

			apartmentInfo = PropertyUtils.turnToEntity1(apartmentInfo);
			// 获取该房屋可以预缴的缴费类目(单房屋)
			List<Rule> rules = this.getPreRule(commID,
					apartmentInfo.get("apartmentID").toString(), null,
					billDto.getStartTime());

			// 获取该房屋可预缴类目的最新缴费时间

			Map<String, Map<String, Object>> maxDates = feeDetailService
					.findFeeDetailMaxDate(apartmentInfo.get("apartmentID")
							.toString(), null, "1");

			Map<String, PreDetail> p = new HashMap<String, PreDetail>();

			if (rules == null || rules.size() == 0) {
				continue;
			}

			for (Rule rule : rules) {
				startTime = billDto.getStartTime();
				// 验证时间
				if (maxDates.get(rule.getFeeTypeID()) != null) {

					tempDate = maxDates.get(rule.getFeeTypeID()).get("maxdate")
							.toString();

					if (tempDate.compareTo(endTime) >= 0) {

						continue;
					} else {
						tempDate = DateUtil.addMonth(tempDate, 1);
						// 设置开始时间
						startTime = tempDate.compareTo(startTime) > 0 ? tempDate
								: startTime;
					}

				}

				if (ruleList.get(rule.getRuleID()) == null) {

					if ("2".equals(rule.getPeriodType())) {

						endTime = DateUtil.getLastQuarter(endTime);

						if (startTime.compareTo(endTime) > 0) {

							continue;

						}
					}

					rule.init(false);
					if (rule.getIsValid() == -1) {

					} else {

						propFeeComputeRuleService.checkRule(commID, rule);

					}

				} else {

					rule = ruleList.get(rule.getRuleID());

				}
				rule.setStartDate(startTime);
				rule.setEndDate(endTime);

				if (rule.getIsValid() == -1 || !rule.getCheckRes()) {

					continue;

				}

				propFeeComputeRuleService.setRuleParam(rule, apartmentInfo,
						null);

				BigDecimal d = rule.complete(rule.getParam());
				if (d != null) {

					d = d.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP);

					if (d.compareTo(BigDecimal.ZERO) > 0) {

						Map<String, String> param = new HashMap<>();

						temp = BigDecimal.ZERO;
						for (String date : rule.getResList2(d.toString())) {

							temp = temp.add(d);
						}
						// amounts.put("code", code);
						// amounts.put("feeAmount", rule.getFeeAmount());
						// amounts.put("feePrice", rule.getFeePrice());
						// code = codes.get(rule.getFeeTypeID());

						// PreDetail p1 = p.get(code);
						PreDetail p1 = p.get(rule.getFeeTypeID());
						if (p1 == null) {

							p1 = new PreDetail();
							p1.setStartDate(rule.getStartDate());
							p1.setEndDate(rule.getEndDate());
							p.put(rule.getFeeTypeID(), p1);
						}

						if (p1.getFeeAmount() == null
								&& rule.getFeeAmount() != null) {

							p1.setFeeAmount(rule.getFeeAmount());
						}
						if (p1.getFeePrice() == null
								&& rule.getFeePrice() != null) {

							p1.setFeePrice(rule.getFeePrice());
						}

						p1.setAmount(p1.getAmount().add(temp));

					}

				}

			}

			res.put(apartmentInfo.get("apartmentID").toString(), p);

		}

		return res;

	}

	@Override
	public List<String> crePreFeeDetail(String commID, String apartmentID,
			List<PreFeeDto> preFeeDto) throws Exception, AppBizException {
		List<Map<String, Object>> res = new ArrayList<>();

		List<String> ids = new ArrayList<>();
		for (PreFeeDto preFeeDto2 : preFeeDto) {
			// 根据房屋id,和类型获取规则
			List<Rule> rules = this.getPreRule(commID, apartmentID,
					preFeeDto2.getFeeTypeID(), null);
			if (rules == null || rules.size() == 0 || rules.size() > 1) {

				throw new AppBizException(100001, "预缴规则异常");

			}

			Rule rule = rules.get(0);
			rule.init(false);
			if (rule.getIsValid() == -1) {
				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常");
			}
			rule.setStartDate(preFeeDto2.getStartTime());
			rule.setEndDate(preFeeDto2.getEndTime());
			Map<String, Object> apart = propInfoService
					.getApartmentInfo(apartmentID);
			// 计算预缴金额
			if (apart == null) {

				return null;
			}

			apart = PropertyUtils.turnToEntity1(apart);
			propFeeComputeRuleService.checkRule(commID, rule);
			if (!rule.getCheckRes()) {

				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常请检查");

			}
			propFeeComputeRuleService.setRuleParam(rule, apart, null);

			BigDecimal d = rule.complete(rule.getParam());

			if (d != null) {

				d = d.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP);

				if (d.compareTo(BigDecimal.ZERO) > 0) {

					for (String date : rule.getResList2(d.toString())) {

						Map<String, Object> p = new HashMap<String, Object>();
						p.put("feeDetailID", IdUtil.getuuId());
						p.put("apartmentID", apartmentID);
						p.put("feeTypeID", rule.getFeeTypeID());
						p.put("amount", d.toString());
						p.put("realamount", d);

						p.put("feeAmount", rule.getFeeAmount());
						p.put("feePrice", rule.getFeePrice());

						p.put("ruleID", rule.getRuleID());
						p.put("feeDate", date);
						p.put("status", "0");
						p.put("ispre", "2");
						p.put("type", "2");
						p.put("itemStat", "1");

						// 生成账单
						int r = this.addFeeDetail(p);

						// 返回账单信息
						if (r == 0) {

							List<Map<String, Object>> m = feeDetailService
									.getPropFeeDetails(apartmentID,
											rule.getFeeTypeID(), date);

							if (m == null || m.size() == 0) {

								throw new AppBizException(100001, "预缴信息异常");

							}

							if ("1".equals(m.get(0).get("status").toString())) {

								throw new AppBizException(100001,
										"预缴信息错误，存在已预缴信息");

							}
							ids.add(m.get(0).get("feeDetailID").toString());

						} else {

							ids.add(p.get("feeDetailID").toString());
						}

						// res.add(p);

					}

				}
			} else {

				throw new AppBizException(100001, "缴费类目"
						+ rule.getFeeTypeName() + "的计费规则:" + rule.getRuleName()
						+ "配置异常");

			}

		}
		return ids;
	}

	private ResultInfo checkRule(List<Rule> rules, String commID,
			String startTime, String endTime) throws Exception, AppBizException {

		ResultInfo r = new ResultInfo();
		r.setErrCode(0);
		String errInfo = "";
		boolean isErr = false;
		for (Rule rule2 : rules) {
			rule2.setStartDate(startTime);
			rule2.setEndDate(endTime);
			if (!propFeeComputeRuleService.checkRule(commID, rule2)
					.getCheckRes()) {
				isErr = true;
				errInfo = rule2.getErrInfo();
				break;
			}

		}
		if (isErr) {

			r.setErrCode(-1);
			r.setErrInfo(errInfo);

		}

		return r;
	}

	private void creFeeDetailByRules(String planID, List<Rule> rules,
			Map<String, String> commparam) throws AppBizException, Exception {

		for (Rule rule2 : rules) {
			// 获取关联的用户信息
			List<Map<String, Object>> apartments = propFeeComputeRuleService
					.getApartmentsByRuleID(rule2.getRuleID());
			for (Map<String, Object> map : apartments) {

				this.creFeeDetailByOneRule(planID, rule2, map, commparam);

			}

		}

	}

	private void creFeeDetailByOneRule(String planID, Rule rule,
			Map<String, Object> apart, Map<String, String> commparam)
			throws AppBizException, Exception {

		// 每个关联房屋进行计算

		// 设置计算参数
		propFeeComputeRuleService.setRuleParam(rule, apart, commparam);
		// 计算结果
		BigDecimal res = rule.complete(rule.getParam());

		// 插入缴费细项
		if (res != null
				&& BigDecimal.ZERO.compareTo(res.setScale(rule.getRound(),
						BigDecimal.ROUND_HALF_UP)) < 0) {
			// 根据规则获取要生成的日期遍历生成账单
			for (String date : rule.getResList2(res.toString())) {
				Map<String, Object> p = new HashMap<String, Object>();
				p.put("feeDetailID", IdUtil.getuuId());
				p.put("apartmentID", apart.get("apartmentID"));
				p.put("feeTypeID", rule.getFeeTypeID());
				p.put("amount",
						res.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP)
								.toString());
				p.put("realamount",
						res.setScale(rule.getRound(), BigDecimal.ROUND_HALF_UP)
								.toString());

				p.put("feeAmount", rule.getFeeAmount());
				p.put("feePrice", rule.getFeePrice());

				p.put("ruleID", rule.getRuleID());
				p.put("feeDate", date);
				p.put("status", "0");
				p.put("itemStat", "1");
				p.put("planID", planID);
				int r = this.addFeeDetail(p);
				// 设置原先预缴项为生成状态
				if (r == 0) {
					feeDetailService
							.updateType(apart.get("apartmentID").toString(),
									rule.getFeeTypeID(), date, "1", planID);
				}

			}

		}

	}

	@Override
	@Transactional(rollbackFor = { AppBizException.class, Exception.class,
			RuntimeException.class })
	public void crePreFeeDetail(String commID, String apartmentID)
			throws Exception, AppBizException {

		String period = null;
		String curDate = null;

		period = propFeeCommInfoService.findValByCode(commID, "period");

		curDate = propFeeCommInfoService.findValByCode(commID, "curDate");

		if (period == null) {

			return;
		}

		// 获取当前时间
		String startTime = "";
		String nowTime = DateUtil.fomartDateToString(new Date(), "yyyy-MM");
		String endTime = "";
		startTime = DateUtil.addMonth(curDate, 1);
		// 计算生成的时间
		if ("1".equals(period)) {

			endTime = nowTime;

		} else if ("2".equals(period)) {
			String mm = nowTime.split("-")[1];
			if ("03060912".indexOf(mm) == -1) {
				endTime = DateUtil.getNextQuarter(nowTime);

			} else {
				endTime = nowTime;
			}
			;

		}

		// 已生成的不要再生成
		if (curDate.compareTo(endTime) >= 0) {

			return;

		}

		// 获取固定费用规则
		List<Rule> rules = this.getPreRule(commID, null, null, null);
		// 校验参数
		ResultInfo checkRule = this
				.checkRule(rules, commID, startTime, endTime);
		if (checkRule.getErrCode() != 0) {

			return;
		}

		this.creFeeDetailByRules(null, rules, new HashMap<String, String>());

	}

	@Override
	public void autoCrePreFeeDetail(String commID) throws Exception,
			AppBizException {

		List<Map<String, Object>> comms = new ArrayList<>();

		if (!StringUtils.isBlank(commID)) {

			Map<String, Object> param = new HashMap<>();
			param.put("comm_id", commID);
			comms.add(param);

		} else {

			comms = propFeeCommService.findPropFeeCommByPage(null, null, 1,
					1000000);
		}
		// 获取该系统中的小区信息

		for (Map<String, Object> map : comms) {

			try {
				this.crePreFeeDetail(map.get("comm_id").toString(), null);

			} catch (Exception e) {
				// TODO: handle exception
			}

		}
		for (Map<String, Object> map : comms) {

			try {

				// 获取小区下的房屋余额大于0的房屋信息

				// List<Map<String, Object>>
				// apartList=propInfoService.getAllInfo(map.get("comm_id").toString());
				List<Map<String, Object>> apartList = propFeeAccountService
						.getAountInfoHasMoney(map.get("comm_id").toString());

				for (Map<String, Object> map2 : apartList) {

					offsetService.autoOffset(map.get("comm_id").toString(),
							map2.get("apartment_id").toString(), null, null);

				}

			} catch (Exception e) {
				e.printStackTrace();
				// TODO: handle exception

			}

			// 自动冲抵

			// TODO Auto-generated method stub

		}
	}

}
